home *** CD-ROM | disk | FTP | other *** search
- ;History:413,1
- ;Sat Aug 19 20:49:16 1989 When creating a new buffer, try to avoid compressing memory.
- ;10-10-88 22:10:05 add inverse_seg to adjust_list.
- ;06-03-88 23:47:57 improve buffer_check
- ;05-26-88 23:25:49 added assumes in init_all_buffers
- ;05-26-88 23:24:13 remove external reference to adjust_buffers
- ;04-19-88 22:23:33 restore ax after returning from a buffer_free.
- ;03-29-88 20:59:24 store ' c' or ' e' after expand or compress.
- ;03-13-88 23:01:42 after doing our work, store ' ' to debug.
- ;12-11-87 06:52:36 add buffer_check
- ;12-08-87 22:52:36 add calls to store_debug
- ;12-06-87 00:32:51 add support for four formSegs.
- ;12-06-87 00:18:16 let init_forms allocate as many buffers as it wants.
- ;11-16-87 23:17:35 make memsize private to buffers.asm
- ;11-10-87 23:02:55 more work to do....
- ;11-10-87 21:46:38 ensure that we can treat 'data' as if it were a 'bufseg'.
- ;11-09-87 23:12:03 start writing buffer_free.
- .xlist
- include memory.def
-
- bufseg segment public
-
- extrn prev_buffer: word ;= segment of prev buffer (0 if none)
- extrn next_buffer: word ;= segment of next buffer (0 if none)
-
- extrn toptop: word
- extrn topbot: word
- extrn bottop: word
- extrn botbot: word
- extrn new_size: word
-
- memsize dw ?
-
- extrn bufseg_size: word
-
- bufseg ends
-
-
- data segment byte public
-
- extrn lomem: byte, lomem_end: byte
-
- public textseg
- textseg dw ? ;bufseg of current text buffer.
- current_seg dw ? ;bufseg of buffer_free caller.
- saveDS dw ?
- saveES dw ?
-
- last_para dw ? ;segment after highest buffer
- memory_end dw ? ;segment after highest buffer right now.
- num_buffers dw ?
- amount_needed dw ? ;amount that we need to be free.
- free_paras dw ? ;number of free paragraphs left.
- insert_number dw ? ;number of buffer being inserted from.
- insert_mark db ? ;mark in buffer being inserted from.
-
- extrn w1_windseg: word, w2_windseg: word ;from redisp.asm
- extrn inverse_seg: word ;from redisp.asm
- extrn syntax_seg: word ;from mintform.asm
- extrn formSeg0: word ;from mintform.asm
- extrn formSeg1: word ;from mintform.asm
- extrn formSeg2: word ;from mintform.asm
- extrn formSeg3: word ;from mintform.asm
-
- adjust_list label word
- dw textseg ;have to adjust this one.
- dw current_seg
- dw w1_windseg ;from redisp.asm, window one's buffer.
- dw w2_windseg ;from redisp.asm, window two's buffer.
- dw inverse_seg
- dw syntax_seg
- dw formSeg0 ;from mintform.asm
- dw formSeg1 ;from mintform.asm
- dw formSeg2 ;from mintform.asm
- dw formSeg3 ;from mintform.asm
- dw saveDS
- dw saveES
- dw 0
-
- data ends
-
-
- code segment byte public
- ;all the routines in this segment are entered with ds=data, es=data
- assume cs:code, ds:data, es:data, ss:data
-
- extrn init_forms: near
-
- movmem macro
- local x
- shr cx,1
- jnc x
- movsb
- x: rep movsw
- endm
-
-
- comment /
-
- buffers:
-
- data
- mint string
- text
- ...
-
- a buffer is initially set with bottop=botbot=end of buffer. Then the buffer
- is initialized.
- /
-
- public init_all_buffers
- init_all_buffers:
- ;enter with bx=> first paragraph of unavailable memory.
- ;exit with cy if no buffer available.
- mov memory_end,bx ;remember where memory ends.
- mov last_para,bx ;remember where memory ends.
- assume ds:bufseg
- mov prev_buffer,0 ;only one buffer so far.
- mov next_buffer,0
- mov ax,offset lomem
- mov topbot,ax
- mov bottop,ax
- mov botbot,offset lomem_end
- assume ds:data
- call init_forms ;create as many buffers as init_forms needs.
- jc init__all_buffers_1
- mov cx,offset bufseg_size
- call new_buffer ;create a new buffer.
- jc init__all_buffers_1
- assume ds:bufseg
- call select_buffer ;make this the current buffer.
- call init_vars$ ;init most everything
- call init_marks ;init the rest.
- clc
- push es
- pop ds
- assume ds:data
- init__all_buffers_1:
- ret
-
-
- public percent_full
- percent_full:
- ;return the percent full amount in ax.
- ;destroy ax,cx,dx.
- push ds
- mov ds,textseg
- assume ds:bufseg
- mov ax,100
- mov cx,memsize
- jcxz percent_full_1
- mov ax,botbot ;compute the size of the buffer
- sub ax,bottop
- add ax,topbot
- sub ax,toptop
- mov dx,0
- div cx
- cmp dx,0
- je percent_full_1
- inc ax
- percent_full_1:
- pop ds
- assume ds:data
- ret
-
-
- public buffer_allocate
- buffer_allocate:
- ;entry:
- ; case cx of
- ; -1..-32768: report the current buffer number.
- ; exit: ax=current buffer number.
- ; 0: create a new buffer.
- ; exit: ax=new buffer number if enough memory, ax=0 otherwise.
- ; 1..32767:
- ; entry: cx=buffer number to select, ax=0 for read/write buffer.
- ; exit: ax=buffer number if it exists, ax=0 otherwise.
- jcxz buffer_allocate_2
- or cx,cx ;if cx<0, return buffer number.
- js buffer_allocate_4
- call find_buffer
- jc buffer_allocate_5 ;buffer not found.
-
- push ds
- mov ds,dx ;get the current buffer back.
- call select_buffer
- pop ds
-
- jmp buffer_allocate_4
-
- buffer_allocate_5:
- mov ax,0 ;buffer not found.
- jmp short buffer_allocate_1
- buffer_allocate_2:
- ;create a new buffer.
- mov cx,offset bufseg_size
- call new_buffer
- mov ax,0 ;failed to create buffer - report it.
- jc buffer_allocate_1
- assume ds:bufseg
- call select_buffer ;make this the current buffer.
- call init_vars$ ;init most everything
- call init_marks ;init the rest.
- push es
- pop ds
- assume ds:data
- buffer_allocate_4:
- ;return the current buffer number.
- mov bx,textseg
- call buffer_number ;return number in ax.
- buffer_allocate_1:
- push es
- pop ds
- assume ds:data
- ret
-
-
- public buffer_insert
- buffer_insert:
- ;enter with al=mark, cx=buffer number.
- ;insert the text between point and mark from the given buffer.
- ;exit with nc if ok, cy if the given buffer doesn't exist, or the specified
- ; text won't fit.
- mov insert_number,cx
- mov insert_mark,al
-
- call find_buffer ;find their buffer.
- jc buffer_insert_1 ;not found.
-
- ;get the size of the inserted text, and make sure we have that much free
- ;space.
- push ds
- mov ds,dx
- assume ds:bufseg
- mov al,insert_mark
- call read_mark$ ;we're just interested in the count.
- mov ax,textseg ;now free that many bytes.
- call buffer_free
- pop ds
- assume ds:data
- jc buffer_insert_1 ;go if it won't fit.
-
- ;now find the buffer again, get the mark, and insert it.
- mov cx,insert_number
- call find_buffer ;this should ALWAYS return nc.
- mov al,insert_mark
- mov ds,dx
- assume ds:bufseg
- call read_mark$
- mov ax,ds
- mov ds,textseg
- call insert_string$ ;this should ALWAYS return nc.
- jmp short buffer_insert_2
- buffer_insert_1:
- stc
- buffer_insert_2:
- push es ;restore ds.
- pop ds
- assume ds:data
- ret
-
-
- public compact_buffers
- compact_buffers:
- ;exit with bx=first unused paragraph.
- call compress
- push ds
- mov ds,textseg
- assume ds:bufseg
- ; mov cx,1000h ;give the current buffer all that
- ; call adjust_new_size ; we can.
- call expand
- call get_last_buffer ;get ds = paragraph of last buffer.
- call buffer_paragraphs ;get the size of it.
- mov bx,ds
- add bx,cx
- pop ds
- mov last_para,bx
- ret
-
-
- public uncompact_buffers
- uncompact_buffers:
- mov ax,memory_end
- mov last_para,ax
- ret
-
-
- compress:
- ;move all the buffers as low in memory as they'll go.
- ;exit with bx=first unused paragraph, num_buffers set to the number of buffers.
- mov ax,'*c'
- call store_debug
-
- push ds
- assume ds:bufseg
-
- mov num_buffers,0
-
- mov ax,ds ;get set to compress data.
- mov es,ax
- mov di,topbot ;put the bottom at the end of the top.
- mov si,bottop ;have to get the copy, just in case.
- mov bottop,di ;save the new bottop.
- mov cx,botbot
- sub cx,si ;same as sub cx,bottop
- movmem
- mov botbot,di
-
- compress_4:
- inc num_buffers
- call buffer_paragraphs
- mov new_size,cx ;remember it for later.
- cmp next_buffer,0 ;was this the last buffer in memory?
- je compress_3 ;yes - we're done.
-
- call move_buffer_lower
- jmp compress_4
- compress_3:
- mov bx,ds ;get the para of the last buffer.
-
- call buffer_paragraphs
- add bx,cx ;compute the first free segment.
-
- pop ds
- assume ds:data
-
- mov ax,last_para ;get the end of memory.
- sub ax,bx ;compute the amount free.
- mov free_paras,ax ;remember it.
-
- mov ax,' c'
- call store_debug
-
- ret
-
-
- public find_buffer
- find_buffer:
- ;enter with cx=buffer number.
- ;exit with nc, dx set to that buffer if it exists, cy otherwise.
- push ds
- assume ds:bufseg
- add cx,4 ;allow for the forms buffer(s).
- find_buffer_1:
- mov dx,next_buffer
- cmp dx,0 ;at the end?
- je find_buffer_2
- mov ds,dx
- loop find_buffer_1
- mov dx,ds ;get the current buffer back.
- pop ds
- clc
- ret
- find_buffer_2:
- pop ds
- stc
- ret
- assume ds:data
-
-
- public new_buffer
- new_buffer:
- ;create a new buffer of size cx.
- ;exit with cy if there's not enough memory for a new buffer, or else return
- ; with ds = new buffer.
-
- ;first we try it by compressing just the last buffer.
- push cx
-
- push cx
- call compress_last ;compress just the last buffer.
- pop cx
- call new_buffer_subr
- pop cx
- jnc new_buffer_3 ;if it worked, we're okay.
-
- push cx
- call compress ;otherwise, compress memory.
- pop cx
- call new_buffer_subr
- new_buffer_3:
- ret
-
-
- compress_last:
- ;exit with the last buffer in memory compressed.
-
- compress_last_1:
- assume ds:bufseg
- mov dx,ds ;remember the current buffer.
- mov ax,next_buffer ;keep going until we have the
- mov ds,ax ; last buffer.
- or ax,ax
- jne compress_last_1
-
- assume es:bufseg
- mov ds,dx ;get the para of the last buffer.
- mov es,dx
-
- mov di,topbot
- mov si,es:bottop ;have to get the copy, just in case.
- mov es:bottop,di ;save the new bottop.
- mov cx,es:botbot
- sub cx,si ;same as sub cx,bottop
- movmem
- mov es:botbot,di
-
- mov ax,data
- mov es,ax
- mov ds,ax
- assume ds:data, es:data
-
- ret
-
-
- new_buffer_subr:
- ;see if there's enough memory for the new buffer, and create it if there is.
- push cx
-
- new_buffer_2:
- assume ds:bufseg
- mov dx,ds ;remember the current buffer.
- mov ax,next_buffer ;keep going until we have the
- mov ds,ax ; last buffer.
- or ax,ax
- jne new_buffer_2
-
- mov ds,dx ;get the para of the last buffer.
- call buffer_paragraphs ;compute the size of it.
- add dx,cx ;find the end of it.
-
- pop cx
- mov ax,cx
- add ax,0fh ;get the size rounded up.
- shr ax,1
- shr ax,1
- shr ax,1
- shr ax,1
- add ax,dx
- cmp ax,last_para ;is there enough memory for new buffer?
- jae new_buffer_1 ;no.
- mov next_buffer,dx ;link to the new buffer.
- mov ax,ds
- mov ds,dx
- mov prev_buffer,ax ;link back to the old buffer.
- mov next_buffer,0 ;and no link to a new buffer.
- mov topbot,cx ;start with an empty buffer.
- mov bottop,cx
- mov botbot,cx
- clc
- ret
- new_buffer_1:
- push es
- pop ds
- assume ds:data
- stc
- ret
-
-
- code ends
-
-
- code segment byte public
- ;all the code in this segment is entered with ds=bufseg, es=data
- assume cs:code, ds:bufseg, es:data
-
- ;the following externs are in 'memory'
- extrn init_vars$: near
- extrn insert_string$: near
- extrn read_mark$: near
-
-
- ;the following externs are in 'marks'
- extrn init_marks: near
-
- ;the following externs are in machine dependent.
- extrn store_debug: near
-
- public buffer_free, expand, adjust_all, adjust_new_size
- public adjust_segments, select_buffer, move_buffer_higher
- public move_buffer_lower, buffer_paragraphs
-
-
- public buffer_check
- buffer_check:
- ;exit with zr if all is ok, nz if we have a bad link.
- push ds
- mov ax,ss
- mov ds,ax
- mov cx,256
- buffer_check_1:
- cmp next_buffer,0 ;if we're done, exit.
- je buffer_check_2
- mov ax,ds ;remember this buffer.
-
- if 0
- mov bx,botbot
- add bx,10h ;round up to next paragraph.
- rcr bx,1 ;ensure that 65536 bytes becomes
- shr bx,1 ; 1000h paragraphs.
- shr bx,1
- shr bx,1
- add bx,ax ;compute the next possible location
- cmp bx,next_buffer ; for the next buffer.
- ja buffer_check_2 ;go if we somehow overlap.
- endif
-
- mov ds,next_buffer ;go to the next buffer.
- cmp ax,prev_buffer ;does the next buffer point to us?
- loope buffer_check_1 ;keep going if we're still ok.
- buffer_check_2:
- pop ds
- ret
-
-
-
- public buffer_number
- buffer_number:
- ;enter with bx=paragraph of buffer.
- ;exit with ax=number of buffer.
- push ds
- mov ax,ss
- mov ds,ax
- xor ax,ax
- buffer_number_1:
- mov dx,ds
- cmp dx,bx ;is this the one we're looking for.
- je buffer_number_2 ;yes - we've got its number.
- mov ds,next_buffer ;get the next buffer
- inc ax
- jmp buffer_number_1
- buffer_number_2:
- pop ds
- sub ax,4 ;allow for the forms buffer(s).
- ret
-
-
- buffer_free:
- ;ensure that the buffer in ax has cx bytes free. If it doesn't, reallocate
- ; memory between the buffers. Return with cy if we cannot get enough memory.
- ; return with nc, ax = new location of buffer.
- mov saveDS,ds
- mov ds,ax
- assume ds:bufseg, es:nothing
- mov ax,bottop ;get the free space size.
- sub ax,topbot
- cmp cx,ax ;go if we have that much space.
- ja buffer_free_1
- mov ax,ds
- mov ds,saveDS
- clc
- ret
- buffer_free_1:
-
- push bx
- push cx
- push dx
- push si
- push di
- mov saveES,es
-
- mov amount_needed,cx ;remember how much we need.
-
- mov current_seg,ds
- mov ax,ss
- mov ds,ax
- call compress ;move them down all the way.
- mov ds,current_seg
-
- ;compact buffers also sets new_size to the new total size of the buffer,
- ; and sets num_buffers to the number of buffers, and sets free_paras to
- ; the number of free paragraphs.
- mov cx,amount_needed ;compute the amount for this buffer.
- add cx,0fh
- rcr cx,1 ;ensure that 65536 bytes becomes
- shr cx,1 ; 1000h paragraphs.
- shr cx,1
- shr cx,1
- cmp cx,ax ;do we have that much?
- ja buffer_free_2 ; no - it's hopeless.
- mov ax,new_size ;get the current size of the buffer.
- add ax,cx ; add in the size that we need.
- cmp ax,1000h ;more than a buffer can possibly hold?
- jae buffer_free_2 ; yes - it's hopeless
-
- ;now give our buffer the amount that it needs.
- call adjust_new_size ;if we don't have enough memory,
-
- mov ax,free_paras ;get the free paragraphs, and divide it
- mov dx,0 ; evenly among all the buffers.
- div num_buffers
-
- mov cx,ax ;allocate the memory evenly.
- call adjust_all ;adjust all the buffers.
-
- cmp free_paras,0 ;is there any memory left?
- je buffer_free_3 ;no - we're done allocating.
-
- mov cx,65535 ;now allocate the rest of the memory.
- call adjust_all
- buffer_free_3:
- call expand
- clc
- jmp short buffer_free_4
- buffer_free_2:
- stc
- buffer_free_4:
- mov es,saveES
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- mov ax,ds
- mov ds,saveDS
- ret
- assume es:data
-
-
- expand:
- ;exit with ds=data.
- mov ax,'*e'
- call store_debug
-
- call get_last_buffer
- ;now we have ds=paragraph of the last buffer, dx->new location for this buffer.
- expand_2:
- mov ax,dx ;get the destination paragraph.
- call move_buffer_higher ;move the buffer up.
- mov ax,prev_buffer ;get the previous buffer.
- or ax,ax
- je expand_1 ;go if we're done.
- mov dx,ds ;remember where we are now.
- mov ds,ax
- sub dx,new_size ;find out where we'll be next.
- jmp expand_2
- expand_1:
- mov ax,' e'
- call store_debug
-
- ret
-
-
- get_last_buffer:
- ;exit with dx = paragraph of new last buffer,
- ; ds = paragraph of current last buffer.
- mov dx,ss ;add up the new sizes of the buffers.
- mov ds,dx
- get_last_buffer_1:
- cmp next_buffer,0 ;is this the last buffer?
- je get_last_buffer_2 ;yes - we're done.
- add dx,new_size ;no - add in the size of this buffer,
- mov ds,next_buffer ;and go to the next buffer.
- jmp get_last_buffer_1
- get_last_buffer_2:
- ret
-
-
- adjust_all:
- ;enter with cx = amount of memory to allocate to each buffer.
- ;add this amount to the new size of each buffer.
- push ds
- mov ax,ss ;get the first buffer.
- mov ds,ax
- adjust_all_1:
- call adjust_new_size
- mov ax,next_buffer ;is this the last buffer?
- cmp ax,0
- mov ds,ax
- jne adjust_all_1 ;no - go do another.
- pop ds
- ret
-
-
- adjust_new_size:
- ;enter with ds = segment whose new_size we're adjusting.
- ; free_paras = the number of free paragraphs to allocate,
- ; cx = number of paragraphs to allocate to the buffer in ds.
- ;return with cy if we don't have enough memory to allocate that many.
- mov ax,1000h ;get the max buffer size.
- sub ax,new_size ;subtract off the new size.
- cmp ax,cx ;more than we want?
- jb adjust_new_size_1 ; no - we can only give it this much.
- mov ax,cx ; yes - only give it as much as we want.
- adjust_new_size_1:
- cmp ax,free_paras ;more than we have?
- jb adjust_new_size_2 ; no - we can give it this much.
- mov ax,free_paras ; yes - only give it as much as we have.
- adjust_new_size_2:
- add new_size,ax
- sub free_paras,ax ;say that we have that many fewer.
- ret
-
-
- adjust_segments:
- ;enter with bx = current bufseg, ax = new location of that bufseg.
- push si
- push di
- mov si,offset adjust_list
- adjust_segments_1:
- mov di,data:[si] ;get the next pointer.
- add si,2
- or di,di ;exit on null.
- je adjust_segments_2
- cmp data:[di],bx ;is this the old one?
- jne adjust_segments_1 ;no.
- mov data:[di],ax ;yes - update with the new.
- jmp adjust_segments_1
- adjust_segments_2:
- pop di
- pop si
- ret
-
-
- select_buffer:
- ;enter with ds=buffer to select.
- mov textseg,ds ;save the new current buffer.
- mov ax,botbot
- sub ax,toptop
- mov dx,0
- mov cx,100
- div cx
- mov memsize,ax
- ret
-
-
- move_buffer_higher:
- ;move a buffer higher in memory.
- ;enter with ax = new buffer location, new_size = new buffer size (in paras).
- push es
- mov bx,ds
- call adjust_segments
- mov es,ax
- assume es:bufseg
-
- std ;moving from low to high, go backwards.
-
- mov si,botbot ;get the last location used in a buffer,
- dec si
-
- mov di,new_size ;compute the new last location in the
- shl di,1 ; buffer.
- shl di,1
- shl di,1
- shl di,1
- dec di
- dec di
-
- mov cx,botbot ;compute the amount to move.
- sub cx,bottop
-
- mov botbot,di
- inc botbot
- rep movsb
- mov bottop,di
- inc bottop
-
- mov si,topbot ;now move the bottom part of the buffer.
- dec si
- mov di,si
- mov cx,topbot
- rep movsb
-
- cld ;now update the previous and next ptrs.
- mov si,es:prev_buffer
- mov di,es:next_buffer
-
- or si,si ;is there a previous buffer?
- je move_buffer_higher_1 ;no.
- mov ds,si
- mov next_buffer,ax ;tell it where we are now.
- move_buffer_higher_1:
-
- or di,di ;is there a next buffer?
- je move_buffer_higher_2 ;no.
- mov ds,di ;get the next buffer.
- mov prev_buffer,ax ;tell it where we are now.
- move_buffer_higher_2:
-
- mov ds,ax ;and return ds = us.
- pop es
- assume es:data
- ret
-
-
- move_buffer_lower:
- ;move a buffer lower in memory.
- ;enter with ds=buffer before the one to be lowered.
- ;exit with ds=new location of lowered buffer.
- call buffer_paragraphs
-
- mov ax,ds ;get the base of this buffer.
- add ax,cx ;get the end of this buffer.
- mov bx,next_buffer
- mov next_buffer,ax ;save the pointer to the next buffer.
- mov cx,ds
- mov ds,bx ;get paragraph of buffer to move.
- mov prev_buffer,cx ;now remember where the previous buffer is.
-
- call adjust_segments
-
- push es
- mov es,ax ;move the bottom down to the new buffer.
- assume es:bufseg
- mov si,0
- mov di,si
- mov cx,topbot
- movmem
-
- mov si,es:bottop ;have to get the copy, just in case.
- mov es:bottop,di ;save the new bottop.
- mov cx,es:botbot
- sub cx,si ;same as sub cx,bottop
- movmem
- mov es:botbot,di
-
- pop es
- assume es:data
- mov ds,ax ;get new para of just moved buffer.
- ret
-
-
- buffer_paragraphs:
- ;compute the number of paragraphs used by a buffer.
- ;enter with ds=buffer
- ;exit with cx=number of paragraphs.
- mov cx,botbot
- add cx,10h ;round up to next paragraph.
- rcr cx,1 ;ensure that 65536 bytes becomes
- shr cx,1 ; 1000h paragraphs.
- shr cx,1
- shr cx,1
- ret
-
-
- code ends
-
- end
-